package net.jxtz.jxtzos.controller.spider;


import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.jxtz.jxtzos.entity.spider.*;
import net.jxtz.jxtzos.entity.spider.vo.SpiderDownloadVo;
import net.jxtz.jxtzos.entity.web.R;
import net.jxtz.jxtzos.service.spider.*;
import net.jxtz.jxtzos.spider.SpiderDefinition;
import net.jxtz.jxtzos.spider.SpiderFactory;
import net.jxtz.jxtzos.spider.process.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * @author a123
 */
@CrossOrigin
@RequestMapping(value = "/spider")
@RestController
@Slf4j
public class SpiderController {

    private final static String SPIDER_LOG_DATABASE_COLUMN = "spider_log_id";
    private final static String SPIDER_LOG_DATABASE_COLUMN_CAPITALIZE = "spiderLogId";

    @SneakyThrows
    @RequestMapping(value = "/excel", method = RequestMethod.GET)
    public void excel(@RequestParam("spiderLogId") Long spiderLogId, @RequestParam("spiderCode") String spiderCode, HttpServletResponse response) {
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode(LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE), "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        switch (spiderCode) {
            case BeiKeProcessor.SPIDER_NAME:
                List<SpiderBeike> spiderBeikes = beikeService.list(new QueryWrapper<SpiderBeike>().eq(SPIDER_LOG_DATABASE_COLUMN_CAPITALIZE, spiderLogId));
                EasyExcel.write(response.getOutputStream(), SpiderBeike.class).sheet("1").doWrite(spiderBeikes);
                break;
            case HousingInformationProcessor.SPIDER_NAME:
                List<SpiderHousingInformation> spiderHousingInformations = housingInformationService.list(new QueryWrapper<SpiderHousingInformation>().eq(SPIDER_LOG_DATABASE_COLUMN_CAPITALIZE, spiderLogId));
                EasyExcel.write(response.getOutputStream(), SpiderHousingInformation.class).sheet("1").doWrite(spiderHousingInformations);
                break;
            case JingDongProcessor.SPIDER_NAME:
                List<SpiderJingdong> jingdongs = jingdongService.list(new QueryWrapper<SpiderJingdong>().eq(SPIDER_LOG_DATABASE_COLUMN_CAPITALIZE, spiderLogId));
                EasyExcel.write(response.getOutputStream(), SpiderJingdong.class).sheet("1").doWrite(jingdongs);
                break;
            case SpiderLandTransactionV2Processor.SPIDER_NAME:
                List<SpiderLandTransactionV2> landTransactionV2s = landTransactionV2Service.list(new QueryWrapper<SpiderLandTransactionV2>().eq(SPIDER_LOG_DATABASE_COLUMN_CAPITALIZE, spiderLogId));
                EasyExcel.write(response.getOutputStream(), SpiderLandTransactionV2.class).sheet("1").doWrite(landTransactionV2s);
                break;
            case XinJianHousingInformationProcessor.SPIDER_NAME:
                List<SpiderXinjianHousing> xinjianHousings = xinjianHousingService.list(new QueryWrapper<SpiderXinjianHousing>().eq(SPIDER_LOG_DATABASE_COLUMN, spiderLogId));
                EasyExcel.write(response.getOutputStream(), SpiderXinjianHousing.class).sheet("1").doWrite(xinjianHousings);
                break;
            case XinJianInSaleHousingProcessor.SPIDER_NAME:
                List<SpiderXinjianInSaleHousing> xinjianInSaleHousings = xinjianInSaleHousingService.list(new QueryWrapper<SpiderXinjianInSaleHousing>().eq(SPIDER_LOG_DATABASE_COLUMN, spiderLogId));
                EasyExcel.write(response.getOutputStream(), SpiderXinjianInSaleHousing.class).sheet("1").doWrite(xinjianInSaleHousings);
                break;
            case NanchangHousingAuthorityProcessor.SPIDER_NAME:
                List<SpiderNanchangHousingAuthority> nanchangHousingAuthorities = spiderNanchangHousingAuthorityService.list(new QueryWrapper<SpiderNanchangHousingAuthority>().eq(SPIDER_LOG_DATABASE_COLUMN, spiderLogId));
                EasyExcel.write(response.getOutputStream(), SpiderNanchangHousingAuthority.class).sheet("1").doWrite(nanchangHousingAuthorities);
            default:
        }
    }

    @RequestMapping(value = "/pushDownloadOrder", method = RequestMethod.POST)
    public R pushDownloadOrder(@RequestBody SpiderLogServe spiderLogServe) {
        List<SpiderLogServe> list = spiderLogServeService.list(new QueryWrapper<SpiderLogServe>().eq("spider_code", spiderLogServe.getSpiderCode()).eq("is_execute", false));
        if (list.size() <= 0) {
            return spiderLogServeService.save(spiderLogServe) ? R.ok():R.error();
        }else {
            return R.error().message("添加失败，已存在相同预约");
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @RequestMapping(value = "/realTime", method = RequestMethod.POST)
    public R realTimeDownload(@RequestBody SpiderDownloadVo spiderDownloadVo) {
        SpiderFactory instance = SpiderFactory.getInstance();
        SpiderLogServe spiderLogServe = new SpiderLogServe();
        spiderLogServe.setExecute(false);
        BeanUtils.copyProperties(spiderDownloadVo, spiderLogServe);
        spiderLogServeService.save(spiderLogServe);
        SpiderDefinition spiderDefinition = new SpiderDefinition();
        BeanUtils.copyProperties(spiderDownloadVo, spiderDefinition);
        new Thread(() -> {
            instance.invokeSpiderStart(spiderDownloadVo.getSpiderCode(), spiderLogServe, spiderDefinition);
            spiderLogServe.setExecute(true);
            spiderLogServeService.updateById(spiderLogServe);
        });

        return R.ok().message("请求成功，请耐心等待爬取完成");
    }


    @RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
    public R delete(@PathVariable Long id) {
        return spiderLogServeService.removeById(id) ? R.ok():R.error();
    }

    @RequestMapping(value = "/getExecuteSpider", method = RequestMethod.GET)
    public R getExecuteSpider(@RequestParam("spiderCode") String spiderCode) {
        List<SpiderLogServe> list = spiderLogServeService.list(new QueryWrapper<SpiderLogServe>().eq("spider_code", spiderCode).eq("is_execute", 0));
        return R.ok().data("executeList", list);
    }

    @RequestMapping(value = "/getOverExecuteSpiderList", method = RequestMethod.GET)
    public R getOverExecuteSpiderList(@RequestParam("spiderCode") String spiderCode) {
        List<SpiderLogServe> list = spiderLogServeService.list(new QueryWrapper<SpiderLogServe>().eq("is_execute", true).eq("spider_code", spiderCode));
        return R.ok().data("overExecute", list);
    }

    @RequestMapping(value = "/getSpiderList", method = RequestMethod.GET)
    public R getSpiderList(@RequestParam(value = "rowNum", defaultValue = "8") Integer maxSize) {
        List<SpiderDefinition> spiderKey = SpiderFactory.getInstance().getSpiderKey();
        List<List<SpiderDefinition>> list = spiderListHandle(spiderKey, maxSize);
        return R.ok().data("spiderList", list);
    }

    private List<List<SpiderDefinition>> spiderListHandle(List<SpiderDefinition> spiderKey, int maxSize) {
        List<List<SpiderDefinition>> list = new ArrayList<>();
        List<SpiderDefinition> strings = new ArrayList<>();
        int a = 0;
        for (int i = 0; i < spiderKey.size(); i++) {
            a++;
            strings.add(spiderKey.get(i));
            if (a > maxSize - 1) {
                list.add(new ArrayList<>(strings));
                a = 0;
                strings.clear();
            }

            if (i == spiderKey.size() - 1) {
                list.add(new ArrayList<>(strings));
            }
        }
        
        return list;
    }

    private final SpiderLogServeService spiderLogServeService;

    /**
     * 贝壳
     */
    private final ISpiderBeikeService beikeService;

    /**
     * 京东
     */
    private final ISpiderJingdongService jingdongService;

    /**
     * 南昌房信网
     */
    private final SpiderHousingInformationService housingInformationService;

    /**
     * 江西土地交易
     */
    private final SpiderLandTransactionV2Service landTransactionV2Service;

    /**
     * 新建新房
     */
    private final SpiderXinjianHousingService xinjianHousingService;

    /**
     * 新建二手房
     */
    private final SpiderXinjianInSaleHousingService xinjianInSaleHousingService;

    /**
     * 南昌房管局
     */
    private final SpiderNanchangHousingAuthorityService spiderNanchangHousingAuthorityService;

    public SpiderController(SpiderLogServeService spiderLogServeService, ISpiderBeikeService beikeService, ISpiderJingdongService jingdongService, SpiderHousingInformationService housingInformationService, SpiderLandTransactionV2Service landTransactionV2Service, SpiderXinjianHousingService xinjianHousingService, SpiderXinjianInSaleHousingService xinjianInSaleHousingService, SpiderNanchangHousingAuthorityService spiderNanchangHousingAuthorityService) {
        this.spiderLogServeService = spiderLogServeService;
        this.beikeService = beikeService;
        this.jingdongService = jingdongService;
        this.housingInformationService = housingInformationService;
        this.landTransactionV2Service = landTransactionV2Service;
        this.xinjianHousingService = xinjianHousingService;
        this.xinjianInSaleHousingService = xinjianInSaleHousingService;
        this.spiderNanchangHousingAuthorityService = spiderNanchangHousingAuthorityService;
    }

}
